<?php
// +-------------------------------------------------------------------
// | 
// +-------------------------------------------------------------------
// | Copyright (c) 2009-2016 All rights reserved.
// +-------------------------------------------------------------------
namespace Kcdns\Service\Batch;

class Service
{
    const STATUS_RUNNING = 1;
    const STATUS_SUCCESS = 2;
    const STATUS_FAIL = 3;

    private static $count = 0;
    private static $start = 0;
    private static $step = 0;
    private static $stepTitle = '';
    private static $totalStep = 1;

    public function exec($callable, $task_title, $args = [])
    {
        if (!is_callable($callable)) {
            throw new \Exception('invalid callable:' . $callable);
        }

        //服务锁定
        $lock_service = $callable . '|lock';
        if (S($lock_service)) {
            throw new \Exception('任务执行中，请稍后再试');
        }
        S($lock_service, 1);

        //任务所属服务
        $batch_id = uniqid();
        S($batch_id . '|service', $lock_service);
        S($batch_id . '|task_title', join('', ['[', $task_title, ']']));

        $log_file = $this->getBatchLogFile($batch_id);
        $args = $args ? '"' . join('" "', $args) . '"' : '';
        $cmd = [];
        $cmd[] = "cd " . ROOT_PATH;
        $cmd[] = CRON_COMMAND . " index.php Batch/index $batch_id \"$callable\" $args > $log_file 2>&1 & ";
        $shell = join(' && ', $cmd);
        shell_exec($shell);

        S($batch_id . '|status', self::STATUS_RUNNING);
        return $batch_id;
    }

    public function run()
    {
        //php index.php batch/index/index batch_id callable arg1 arg2 ...
        $args = array_slice($GLOBALS['argv'], 2);// index.php batch/index/index
        $batch_id = $args[0];//$batch_id
        $callable = $args[1];//callable
        $arg_arr = array_slice($args, 2);// arg1 arg2 ...

        try {
            call_user_func_array($callable, $arg_arr);
            S($batch_id . '|status', self::STATUS_SUCCESS);
        } catch (\Exception $e) {
            S($batch_id . '|status', self::STATUS_FAIL);
            echo $e->getMessage();
        }
        S($this->getBatchService($batch_id), null);//解锁单任务运行
    }

    public function getBatchTaskTitle($batch_id)
    {
        return S($batch_id . '|task_title');
    }

    public function getBatchService($batch_id)
    {
        return S($batch_id . '|service');
    }

    public function getBatchStatus($batch_id)
    {
        return (int)S($batch_id . '|status');
    }

    public function getBatchLogFile($batch_id)
    {
        return RUNTIME_PATH . $batch_id . '.batch.log';
    }

    public function getBatchInfo($batch_id)
    {
        $status = $this->getBatchStatus($batch_id);
        switch ($status) {
            case self::STATUS_RUNNING:
                $arr = file($this->getBatchLogFile($batch_id));
                $info = end($arr) ?: '[准备中...]';
                break;
            case self::STATUS_SUCCESS:
                $info = '已完成';
                break;
            case self::STATUS_FAIL:
                $arr = file($this->getBatchLogFile($batch_id));
                $info = end($arr);
                break;
            default:
                $info = '无效的任务';
        }
        return [
            $status,
            $info,
            $this->getBatchTaskTitle($batch_id)
        ];
    }

    public function getBatchLog($batch_id)
    {
        return file($this->getBatchLogFile($batch_id));
    }

    public function setTotalStep($total_step)
    {
        self::$totalStep = $total_step;
    }

    public function setCount($count, $title = '')
    {
        self::$count = $count;
        self::$start = 0;
        ++self::$step;
        self::$stepTitle = $title;
    }

    public function setProgress($title = '')
    {
        $count = self::$count;
        $start = ++self::$start;
        $step = self::$step;
        $totalStep = self::$totalStep;
        $stepTitle = self::$stepTitle ? join('', ['[', self::$stepTitle, ']']) : '';
        $percent = number_format($start / $count * 100, 2, '.', '');
        echo join(' ', [
            "[$step/$totalStep]",
            "[$start/$count]",
            "[$percent%]",
            $stepTitle,
            $title,
            PHP_EOL
        ]);
    }
}